home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 333_02 / obstack.c < prev    next >
C/C++ Source or Header  |  1989-04-21  |  5KB  |  179 lines

  1. /* obstack.c - subroutines used implicitly by object stack macros
  2.    Copyright (c) 1986 Free Software Foundation, Inc.
  3. */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "awk.h"
  9. #include "obstack.h"
  10.  
  11.  
  12. STATIC VOID NEAR PASCAL i_obstack_begin(struct obstack *h,
  13.                     VOID *(*chunkfun)());
  14. STATIC VOID NEAR PASCAL i_obstack_newchunk(struct obstack *h,
  15.                        VOID *(*chunkfun)(),
  16.                        int length);
  17. STATIC VOID NEAR PASCAL i_obstack_free(struct obstack *h,
  18.                        VOID (*freechunkfun)(),
  19.                        char *obj);
  20.  
  21.  
  22. VOID NEAR PASCAL i_obstack_begin(struct obstack *h, VOID *(*chunkfun)())
  23. {
  24.     register OBCHUNK          *chunk;       /* points to new chunk */
  25.  
  26.     chunk       = h->chunk = (OBCHUNK *) (*chunkfun)(h->chunk_size);
  27.     h->next_free   = h->object_base = chunk->obstack_l_0;
  28.     h->chunk_limit = chunk->obstack_l_limit = (char *) chunk + h->chunk_size;
  29.     chunk->obstack_l_prev = 0;
  30.     return;
  31. }
  32.  
  33.  
  34. /* Allocate a new current chunk for the obstack *H
  35.    on the assumption that LENGTH bytes need to be added
  36.    to the current object, or a new object of length LENGTH allocated.
  37.    Copies any partial object from the end of the old chunk
  38.    to the beginning of the new one.  */
  39.  
  40. VOID NEAR PASCAL i_obstack_newchunk(struct obstack *h, VOID *(*chunkfun)(),
  41.                     int length)
  42. {
  43.     register OBCHUNK   *old_chunk = h->chunk;
  44.     register OBCHUNK   *new_chunk;
  45.     register long    new_size;
  46.     register int    obj_size = h->next_free - h->object_base;
  47.  
  48.     /* Compute size for new chunk.  */
  49.     new_size = (obj_size + length) << 1;
  50.     if (new_size < h->chunk_size)
  51.     new_size = h->chunk_size;
  52.  
  53.     /* Allocate and initialize the new chunk.  */
  54.     new_chunk = h->chunk = (OBCHUNK *) (*chunkfun)(new_size);
  55.     if (NULL == new_chunk)
  56.     panic("Out of memory in function i_obstack_newchunk");
  57.     new_chunk->obstack_l_prev = old_chunk;
  58.     new_chunk->obstack_l_limit = h->chunk_limit =
  59.                   (char *) new_chunk + new_size;
  60.  
  61.     /* Move the existing object to the new chunk.  */
  62.     memcpy(new_chunk->obstack_l_0, h->object_base, obj_size);
  63.     h->object_base = new_chunk->obstack_l_0;
  64.     h->next_free   = h->object_base + obj_size;
  65.     return;
  66. }
  67.  
  68.  
  69. VOID NEAR PASCAL i_obstack_free(struct obstack *h, VOID (*freechunkfun)(),
  70.                 char *obj)
  71. {
  72.     register OBCHUNK    *lp;     /* below addr of any objects in this chunk */
  73.     register OBCHUNK    *plp;     /* point to previous chunk if any */
  74.  
  75.     lp = (h)->chunk;
  76.     while (lp != 0 && ((char *) lp > obj || (h)->chunk_limit < obj))
  77.     {
  78.     plp = lp->obstack_l_prev;
  79.     (*freechunkfun)(lp);
  80.     if (lp == plp)
  81.         plp = 0;
  82.     lp = plp;
  83.     }
  84.     if (lp)
  85.     {
  86.     (h)->object_base = (h)->next_free = (char *) (obj);
  87.     (h)->chunk_limit = lp->obstack_l_limit;
  88.     (h)->chunk     = lp;
  89.     }
  90.     else
  91.     if (obj != 0)       /* obj is not in any of the chunks! */
  92.         abort();
  93.     return;
  94. }
  95.  
  96.  
  97. VOID PASCAL obstack_begin(OBSTACK *h, int try_length)
  98. {
  99.     h->chunk_size = try_length + sizeof(OBCHUNK);
  100.     h->alignment_mask = (1 << 2) - 1;
  101.     i_obstack_begin(h, obstack_chunk_alloc);
  102.     return;
  103. }
  104.  
  105.  
  106. VOID PASCAL obstack_grow(OBSTACK *h, char *where, int length)
  107. {
  108.     if (h->next_free + length > h->chunk_limit)
  109.     i_obstack_newchunk(h, obstack_chunk_alloc, length);
  110.  
  111.     memcpy(h->next_free, where, length);
  112.     h->next_free += length;
  113.     return;
  114. }
  115.  
  116.  
  117. VOID PASCAL obstack_grow0(OBSTACK *h, char *where, int length)
  118. {
  119.     if (h->next_free + length + 1 > h->chunk_limit)
  120.     i_obstack_newchunk(h, obstack_chunk_alloc, length + 1);
  121.  
  122.     memcpy(h->next_free, where, length);
  123.     h->next_free += length;
  124.     *(h->next_free)++ = 0;
  125.     return;
  126. }
  127.  
  128.  
  129. VOID PASCAL obstack_1grow(OBSTACK *h, int datum)
  130. {
  131.     if (h->next_free + 1 > h->chunk_limit)
  132.     i_obstack_newchunk(h, obstack_chunk_alloc, 1);
  133.  
  134.     *(h->next_free)++ = datum;
  135.     return;
  136. }
  137.  
  138.  
  139. VOID PASCAL obstack_blank(OBSTACK *h, int length)
  140. {
  141.     if (h->next_free + length > h->chunk_limit)
  142.     i_obstack_newchunk(h, obstack_chunk_alloc, length);
  143.  
  144.     h->next_free += length;
  145.     return;
  146. }
  147.  
  148.  
  149. VOID * PASCAL obstack_finish(OBSTACK *h)
  150. {
  151.     auto     char    *p, *object_base;
  152.  
  153.     h->next_free = (char *) ((unsigned long) (h->next_free + h->alignment_mask)
  154.               & (~((unsigned long) h->alignment_mask)));
  155.  
  156.     p = (char *) h->chunk;
  157.     if (h->next_free - p > h->chunk_limit - p)
  158.     h->next_free = h->chunk_limit;
  159.  
  160.     object_base    = h->object_base;
  161.     h->object_base = h->next_free;
  162.     return(object_base);
  163. }
  164.  
  165.  
  166. VOID PASCAL obstack_free(OBSTACK *h, char *obj)
  167. {
  168.     auto     int     len;
  169.     auto     char    *p;
  170.  
  171.     p    = (char *) h->chunk;
  172.     len = obj - p;
  173.     if (len >= 0 && len < h->chunk_limit - p)
  174.     h->next_free = h->object_base = p + len;
  175.     else
  176.     i_obstack_free(h, obstack_chunk_free, p + len);
  177.     return;
  178. }
  179.